﻿#region USING

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Xml.Linq;

using TestVisioCanvas.Extensions;
using Win32Forms = System.Windows.Forms;
using Visio = Microsoft.Office.Interop.Visio;
using Excel = Microsoft.Office.Interop.Excel;
using VisOcx = AxMicrosoft.Office.Interop.VisOcx;
using TestVisioCanvas.Helpers;
using VB = Microsoft.VisualBasic.Compatibility;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using TestVisioCanvas.Wrappers;
using TestVisioCanvas.Pages;
using TestVisioCanvas.Models;


#endregion
namespace TestVisioCanvas
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {        
        // Flags for context activation
        private bool AddingDWG =false;
        private bool AddingMeasure = false;
        private bool Dragging = false;
        private bool Duplicating = false;
        private bool CopyingDesign = false;

#warning INSERIRE ELEMENTI DI APPOGGIO DA UTILIZZARE DURANTE IL DRAGGING
        private MasterModel draggedMaster;
        private ProductModel draggedProduct;              

        #region Stencil Paths

        private readonly string[] StencilPaths =
        new string[]
        {
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.FurniturePath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.MeasuresPath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.RoomComponentsPath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.AppliancesPath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.BuildingCorePath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.SanitaryPath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.OfficeEquipmentPath,
            Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.OfficeAccessoiresPath
        };

        //private readonly string FurniturePath =
        //    Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.FurniturePath;
        //private readonly string RoomComponents =
        //    Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.RoomComponentsPath;
        //private readonly string MeasurementComponents =
        //    Environment.CurrentDirectory + TestVisioCanvas.Resources.Strings.MeasuresPath;
        #endregion                		

        // Context menu per il drawing control
        Win32Forms.ContextMenuStrip drawingContextMenu;
        
        // viewmodel of the main window
        ViewModel.MainWindowViewModel VM = new ViewModel.MainWindowViewModel();
        // state of the application
        ApplicationState.AppStateManager State = new ApplicationState.AppStateManager();
        
        // Stores temporary the visio shape of a cad drawing in order to modify it after
        // the ShapeAdded event, because in the event handler the CAD properties are not available
        Visio.Shape DWG;
        PageSetup DrawingPageSetup;
        Point lastMousePosition;

        /// <summary>
        /// Standard constructor, initializes the MainWindow with standard values and with a clean
        /// drawing paper with predefined paper format and scale
        /// </summary>
        public MainWindow()
        {            
            CommonConstructionSteps();			
            // set the paper format and scale
            DrawingPageSetup = PageStandards.A4OnetoFiftyHorizontalPage;
            // event handling on the _drawing control activated
            _drawingControl.WindowActivated += (w,e) =>
                InitializeDrawingControl(DrawingPageSetup);
            LoadBasicStencil();

            // event handling when the frame is navigated
            _frame.Navigated += (s, a) =>
                {
                    if (a.Content is VisioControlPage)
                    {
                        _WFHost.Visibility = System.Windows.Visibility.Visible;
                        _frame.Visibility = System.Windows.Visibility.Collapsed;
                        //_zoomSilder.Visibility = System.Windows.Visibility.Visible;
                    }
                };
            
            this.DataContext = VM;            
            _frame.Navigate(new Pages.VisioControlPage());
            // Commentare per lavorare su back page
            // Bisogna verificare che ogni volta che si accede ad una pagina questa non sia nulla,
            // visto che la back page non andrà aggiunta allo stato
            State.PageAdded(_drawingControl.Window.Application.ActivePage.ID,
                _drawingControl.Window.Application.ActivePage.NameU);
            _drawingControl.Window.Application.ActivePage.NameU = "Proposta 1";                                    
            #region TENTATIVO BACK PAGE
            //var bla = _drawingControl.Window.Application.ActivePage;
            //bla.Drop((VM.Masters[0] as MasterModel).Master, 0, 0);
            //bla.Background = 1;
            //var newPage = _drawingControl.Window.Document.Pages.Add();
            //newPage.BackPage = bla;
            #endregion            

            _drawingControl.WindowActivated += new VisOcx.EVisOcx_WindowActivatedEventHandler(_drawingControl_WindowActivated);

            CalculateDynamicMargins();
        }

        /// <summary>
        /// Calcolo di alcune dimensioni sulla base delle dimensioni reali dello schermo.
        /// </summary>
        private void CalculateDynamicMargins()
        {
            //double horMargin = 16 * (System.Windows.SystemParameters.PrimaryScreenWidth / 1440);
            //double verMargin = 14 * (System.Windows.SystemParameters.PrimaryScreenHeight / 900);

            double horMargin = 18 * (System.Windows.SystemParameters.PrimaryScreenWidth / 1440);
            double verMargin = 16 * (System.Windows.SystemParameters.PrimaryScreenHeight / 900);

            double ProductHeight = 139 * (System.Windows.SystemParameters.PrimaryScreenHeight / 900);            
            double ProductWidth = 139 * (System.Windows.SystemParameters.PrimaryScreenWidth / 1440);

            this.Resources.Add("PListMargin", new Thickness(horMargin, verMargin, horMargin, verMargin));
            this.Resources.Add("NListMargin", new Thickness(-horMargin, -verMargin, -horMargin, -verMargin));
            this.Resources.Add("ProductWidth", ProductWidth);
            this.Resources.Add("ProductHeight", ProductHeight);
        }

        void _drawingControl_WindowActivated(object sender, VisOcx.EVisOcx_WindowActivatedEvent e)
        {
            var menu = _drawingControl.Window.Application.BuiltInMenus;
            
            // loops onto the menu tables disabling the shortcuts (or accelerators) 
            // we want to suppress (copy, paste, undo/redo)
            for (int i = 0; i < menu.AccelTables.Count; i++)
            {                
                //System.Diagnostics.Debug.WriteLine(bla[i].TableName);
                for (int j = 0; j < menu.AccelTables[i].AccelItems.Count; j++)
                {
                    var b = menu.AccelTables[i].AccelItems[j];
                    //System.Diagnostics.Debug.WriteLine((Visio.VisUICmds)b.CmdNum);
                    if ((Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdUFEditDuplicate ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdDragDuplicate ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdDuplicateDataGraphic ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdDuplicateTheme ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdPasteShortcut ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdUFEditCopy ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdEditUndo ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdEditUndoMultiple ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdFileUndoCheckout ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdEditRedo ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdEditUndoMultiple ||
                        (Visio.VisUICmds)b.CmdNum == Visio.VisUICmds.visCmdEditRedoOrRepeat)
                    {
                        var t = (Visio.VisUICmds)b.CmdNum;
                        var tableNum = b.Parent.Parent.SetID;
#if DEBUG
                        System.Diagnostics.Debug.WriteLine(string.Format("tabella {0} - accelitem {1}", tableNum, t));
#endif                  // each item must be deleted
                        b.Delete();                        
                    }
                }
            }
            // the resultant menu must be set as custom menu
            _drawingControl.Window.Application.SetCustomMenus(menu);
            
        }

        /// <summary>
        /// Parameterized constructor, initializes the MainWindow following the settings choosen by the user
        /// in the wizard
        /// </summary>
        /// <param name="RoomType">Room type to add</param>
        /// <param name="PageSetup">Settings of the drawing page</param>
        /// <param name="RoomWidth">Width of the room to add</param>
        /// <param name="RoomLength">Height of the room to add</param>
        public MainWindow(RoomType RoomType, PageSetup PageSetup, double RoomWidth,
            double RoomLength)
        {
            CommonConstructionSteps();            
            DrawingPageSetup = PageSetup;
            // applies the choosen page setup to the drawing control
            InitializeDrawingControl(DrawingPageSetup);
            LoadBasicStencil();
            // finds the first model on the list that represents the chosen room
            MasterModel m = VM.Masters.First(x => x.Name == RoomType.ToVisioName());

#warning l'aggiunta della pagina deve essere gestita tramite ManagedShapes
            Visio.Shape addedShape =
                ((Visio.Page)_drawingControl.Window.PageAsObj)
                .Drop(m, VisioUtility.MmToInch(PageSetup.PageCenter.X),
                VisioUtility.MmToInch(PageSetup.PageCenter.Y));
        }

        #region CONTEXT MENU
        /// <summary>
        /// Initializes the contextMenu to be used in the drawing control
        /// </summary>
        private void SetupContextMenu()
        {
            drawingContextMenu = new Win32Forms.ContextMenuStrip();

            // menu item for the measures
            Win32Forms.ToolStripMenuItem quotaItem = new Win32Forms.ToolStripMenuItem();
            quotaItem.Name = "quoteItem";
            quotaItem.Text = "Quote";

            // menu item for the horizontal measure
            Win32Forms.ToolStripMenuItem quotaHor = new Win32Forms.ToolStripMenuItem();
            quotaHor.Name = "quotaHorItem";
            quotaHor.Text = "Quota Orizzontale";

            // menu item for the vertical measure
            Win32Forms.ToolStripMenuItem quotaVert = new Win32Forms.ToolStripMenuItem();
            quotaVert.Name = "quotaVertItem";
            quotaVert.Text = "Quota Verticale";

            // menu item for the diagonal(not a fixed angle) measure
            Win32Forms.ToolStripMenuItem quotaDiag = new Win32Forms.ToolStripMenuItem();
            quotaDiag.Name = "quotaDiagItem";
            quotaDiag.Text = "Quota Diagonale";

            // menu item for the manual measures
            Win32Forms.ToolStripMenuItem quotaManual = new Win32Forms.ToolStripMenuItem();
            quotaManual.Name = "quotaManualItem";
            quotaManual.Text = "Quota Manuale";

            // adds the items to the sub-menu
            quotaItem.DropDown.Items.Add(quotaHor);
            quotaItem.DropDown.Items.Add(quotaVert);
            quotaItem.DropDown.Items.Add(quotaDiag);
            quotaItem.DropDown.Items.Add(quotaManual);

            // menu item for the trasaltion of the selected shapes
            Win32Forms.ToolStripMenuItem traslaItem = new Win32Forms.ToolStripMenuItem();
            traslaItem.Name = "traslaItem";
            traslaItem.Text = "Trasla";

            // menu item for the deletion of the selected shapes
            Win32Forms.ToolStripMenuItem deleteItem = new Win32Forms.ToolStripMenuItem();
            deleteItem.Name = "DeleteItem";
            deleteItem.Text = "Cancella";

#warning da rimuovere o usare per far comparire i dettagli del prodotto
            Win32Forms.ToolStripMenuItem shapeInfoItem = new Win32Forms.ToolStripMenuItem();
            shapeInfoItem.Name = "ShapeInfoItem";
            shapeInfoItem.Text = "Shape Info";

            // adds the items to the menu
            drawingContextMenu.Items.Add(quotaItem);
            drawingContextMenu.Items.Add(traslaItem);
            drawingContextMenu.Items.Add(deleteItem);
            drawingContextMenu.Items.Add(shapeInfoItem);

            _drawingControl.ContextMenuStrip = drawingContextMenu;
            #region Events
            traslaItem.Click += new EventHandler(traslaItem_Click);
            quotaDiag.Click += new EventHandler(quotaDiag_Click);
            quotaHor.Click += new EventHandler(quotaHor_Click);
            quotaVert.Click += new EventHandler(quotaVert_Click);
            quotaManual.Click += new EventHandler(quotaManual_Click);
            deleteItem.Click += new EventHandler(deleteItem_Click);
            shapeInfoItem.Click += new EventHandler(shapeInfoItem_Click);
            #endregion
        }

        #region ContextMenuEventHandlers

        void shapeInfoItem_Click(object sender, EventArgs e)
        {
#warning da sostituire con la visualizzazione del ProductShowcase
            if (_drawingControl.Window.Selection.Count == 1)
            {
                MessageBox.Show((State[ActivePageIndex].Shapes.FirstOrDefault(x => x.ID ==
                _drawingControl.Window.Selection[1].ID) as ManagedShape).Pin.ToString());
            }
        }

        void deleteItem_Click(object sender, EventArgs e)
        {
            // deletes the current selection
            _drawingControl.Window.Selection.Delete();
        }
        /// <summary<>
        /// Event Handler of the QuotaManualItem item of the contextMenu
        /// It adds a standard measure element
        /// </summary> 
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void quotaManual_Click(object sender, EventArgs e)
        {
            if (lastMousePosition != null)
            {
                // enables the measure insertion context
                AddingMeasure = true;
                // insert the measure on the drawing control
                var droppedShape =
                _drawingControl.Window.PageAsObj.Drop(
                    VM.Masters.First(x => x.Name == "Aligned even"), lastMousePosition.X, lastMousePosition.Y);
                droppedShape.CellsU["EndY"].set_Result(StaticUtils.VisioCentimeters,
                    droppedShape.CellsU["BeginY"].get_Result(StaticUtils.VisioCentimeters));
            }
        }

        /// <summary>
        /// Event Handler of the QuotaHorizontalItem item of the contextMenu
        /// It adds a horizontal measure item snapped to the two selected elements
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void quotaHor_Click(object sender, EventArgs e)
        {
            if (_drawingControl.Window.Selection.Count == 2)
            {
                // enables the measure insertion context
                AddingMeasure = true;
                Draw2ShapesMeasure(MeasureType.Horizontal);
            }
            else
            {
                MessageBox.Show(TestVisioCanvas.Resources.Strings.MainPageQuoteClickError);
            }
        }

        /// <summary>
        /// It adds a measure item snapped to the two selected elements
        /// </summary>
        /// <param name="type">The type of the measure; Vertical,Orizontal or Aligned either
        /// internal or external </param>
        private void Draw2ShapesMeasure(MeasureType type)
        {
            bool? inorder = null;

            // find the two managed shapes of the selection
            ManagedShape s1, s2;
            s1 = State[ActivePageIndex].Shapes.FirstOrDefault(x => x.ID == _drawingControl.Window.Selection[1].ID) as ManagedShape;
            s2 = State[ActivePageIndex].Shapes.FirstOrDefault(x => x.ID == _drawingControl.Window.Selection[2].ID) as ManagedShape;

            if (s1 == null || s2 == null)
            {
                throw new Exception("selected shapes are not valid");
            }

            // determines if the shapes must be takein in order (the firs is left, or top) or not.
            if (type == MeasureType.Horizontal)
                inorder = s1.PinX < s2.PinX;

            if (type == MeasureType.Vertical)
                inorder = s1.PinY < s2.PinY;

            if (type == MeasureType.Aligned)
                inorder = true;

            //if (inorder.HasValue)
            //{
            //    Visio.Shape s1, s2;
            //    s1 = inorder.Value ? _drawingControl.Window.Selection[1] : _drawingControl.Window.Selection[2];
            //    s2 = inorder.Value ? _drawingControl.Window.Selection[2] : _drawingControl.Window.Selection[1];

            //    MeasureShapes(type, s1, s2);
            //}

            if (inorder.HasValue && inorder.Value)
            {
                MeasureShapes(type, s1, s2);
            }
            else
            {
                MeasureShapes(type, s2, s1);
            }

        }

        /// <summary>
        /// It adds a mesasure item snapped to the two shapes passed as parameters
        /// </summary>
        /// <param name="s1">The leftmost shape</param>
        /// <param name="s2">The rightmost shape</param>
        /// <param name="type">The type of the measure</param>
        private void MeasureShapes(MeasureType type, ManagedShape s1, ManagedShape s2)
        {
            double offsetX1 = 0, offsetX2 = 0, offsetY1 = 0, offsetY2 = 0;
            ManagedShape ms1, ms2;
            //ms1 = shapes.FirstOrDefault(x => x.ID == s1.ID) as ManagedShape;
            //ms2 = shapes.FirstOrDefault(x => x.ID == s2.ID) as ManagedShape;
            ms1 = s1;
            ms2 = s2;

            if (ms1 == null || ms2 == null)
            {
                throw new ArgumentException("s1 or s2 are not measurable shapes");
            }

            if (type == MeasureType.Horizontal || type == MeasureType.Aligned)
            {
                // calculates the horizontal offset and places the measure
                offsetX1 = ms1.Width / 2;
                offsetX2 = ms2.Width / 2;
                PlaceMeasure(type, ms1.Pin.X + offsetX1, ms1.Pin.Y, ms2.Pin.X - offsetX2, ms2.Pin.Y);
            }
            if (type == MeasureType.Vertical || type == MeasureType.Aligned)
            {
                // calculates the vertical offset and places the measure
                offsetY1 = ms1.Height / 2;
                offsetY2 = ms2.Height / 2;
                PlaceMeasure(type, ms1.Pin.X, ms1.Pin.Y + offsetY1, ms2.Pin.X, ms2.Pin.Y - offsetY2);
            }

            //PlaceMeasure(type,
            //    //s1.CellsU["PinX"].get_Result(StaticUtils.VisioCentimeters) 
            //    ms1.Pin.X + offsetX1,
            //    //s1.CellsU["PinY"].get_Result(StaticUtils.VisioCentimeters) 
            //    ms1.Pin.Y+ offsetY1,
            //    s2.CellsU["PinX"].get_Result(StaticUtils.VisioCentimeters) 
            //    - offsetX2,
            //    s2.CellsU["PinY"].get_Result(StaticUtils.VisioCentimeters) 
            //    - offsetY2);
        }

        /// <summary>
        /// Adds a standardmeasure type defined by its type and its endpoint coordinates
        /// </summary>
        /// <param name="type">type of the measure</param>
        /// <param name="BeginX">X coordinate of the first endpoint</param>
        /// <param name="BeginY">Y coordinate of the first endpoint</param>
        /// <param name="EndX">X coordinate of the second endpoint</param>
        /// <param name="EndY">Y coordinate of the second endpoint</param>
        private void PlaceMeasure(MeasureType type, double BeginX, double BeginY, double EndX, double EndY)
        {
            Visio.Shape droppedShape = null;

            var bla = VM.Masters.First(x => x.Name == "Controller dimension");

            if (type == MeasureType.Horizontal)
                bla = VM.Masters.First(x => x.Name == "Horizontal");
            if (type == MeasureType.Vertical)
                bla = VM.Masters.First(x => x.Name == "Vertical");
            if (type == MeasureType.Aligned)
                bla = VM.Masters.First(x => x.Name == "Aligned");

            droppedShape =
                _drawingControl.Window.PageAsObj.Drop(
                   bla.Master, 0, 0);

            if (droppedShape != null)
            {
#warning must be substituted wiht a managed shape instantiation
                droppedShape.CellsSRC[StaticUtils.PropertiesIndex, 2, 0].Formula = "=\"Show Units\"";
                //endpoint1
                droppedShape.CellsU["BeginX"].set_Result(StaticUtils.VisioCentimeters, BeginX);
                droppedShape.CellsU["BeginY"].set_Result(StaticUtils.VisioCentimeters, BeginY);
                //endpoint2
                droppedShape.CellsU["EndX"].set_Result(StaticUtils.VisioCentimeters, EndX);
                droppedShape.CellsU["EndY"].set_Result(StaticUtils.VisioCentimeters, EndY);

                #region IF Controller Dimension
                //switch (type)
                //{
                //    case MeasureType.Horizontal:
                //        droppedShape.CellsU["Angle"].set_Result(Visio.VisUnitCodes.visDegrees, 0);
                //        break;
                //    case MeasureType.Vertical:
                //        droppedShape.CellsU["Angle"].set_Result(Visio.VisUnitCodes.visDegrees, 90);
                //        break;
                //    case MeasureType.Aligned:
                //        break;
                //    case MeasureType.HorizontalOutside:
                //        break;
                //    case MeasureType.VerticalOutside:
                //        break;
                //    case MeasureType.AlignedOutside:
                //        break;
                //    default:
                //        break;
                //}
                #endregion
            }
        }

        /// <summary<>
        /// Event Handler of the QuotaDiagItem item of the contextMenu
        /// It adds a standard measure element
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void quotaDiag_Click(object sender, EventArgs e)
        {
            if (_drawingControl.Window.Selection.Count == 2)
            {
                // enables the measure insertion context
                AddingMeasure = true;
                Draw2ShapesMeasure(MeasureType.Aligned);
            }
            else
            {
                MessageBox.Show(TestVisioCanvas.Resources.Strings.MainPageQuoteClickError);
            }
        }

        /// <summary<>
        /// Event Handler of the QuotaVertItem item of the contextMenu
        /// It adds a standard measure element
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void quotaVert_Click(object sender, EventArgs e)
        {
            if (_drawingControl.Window.Selection.Count == 2)
            {
                // enables the measure insertion context
                AddingMeasure = true;
                Draw2ShapesMeasure(MeasureType.Vertical);
            }
            else
            {
                MessageBox.Show(TestVisioCanvas.Resources.Strings.MainPageQuoteClickError);
            }
        }

        /// <summary>
        /// Event handler of the TrasaItem item of the contextMenu. It opens the dialog window
        /// used to define the traslation parameters.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void traslaItem_Click(object sender, EventArgs e)
        {
            //// works only if almost a shape is selected
            //if (_drawingControl.Window.Selection.Count >= 1)
            //{
            //    // shows the traslation dialog
            //    Dialogs.NewPageDialog tdialog = new Dialogs.NewPageDialog();
            //    bool? isResult = tdialog.ShowDialog();
            //    // if the dialog has a result and it is "valid"
            //    if (isResult.HasValue && isResult.Value)
            //    {
            //        // traslates the objects on the selection
            //        Dialogs.TraslationDialogResult result = tdialog.TraslationResult;
            //        for (int i = 1; i < _drawingControl.Window.Selection.Count + 1; i++)
            //        {
            //            (State[ActivePageIndex].Shapes.First(x => x.ID == _drawingControl.Window.Selection[i].ID) as ManagedShape)
            //                .Translate(result.TraslationX, result.TraslationY);
            //        }
            //    }
            //}
            //else
            //{
            //    MessageBox.Show(TestVisioCanvas.Resources.Strings.MainPageTraslaClickError);
            //}
        }
        #endregion 
        #endregion

        /// <summary>
        /// Adds a shape to the visio drawing control
        /// </summary>
        /// <param name="shapeToAdd">The shape that must be added</param>
        /// <param name="x">The X coordinate</param>
        /// <param name="y">The Y coordinate</param>
        private void AddShapeToVisioCanvas(MasterModel shapeToAdd, double x, double y)
        {
            CopyingDesign = false;
            Point p = VisioUtility.MapWindowsToVisio(_drawingControl,x,y);
            //if the shape is a room, it must be 4*4 meters
            Visio.Master masterToAdd = shapeToAdd.Master;
                Visio.Shape AddedShape = _drawingControl.Window.PageAsObj.Drop(masterToAdd, p.X, p.Y);

            var s = State[ActivePageIndex].Shapes.First(item => item.ID == AddedShape.ID) as ManagedShape;
            
            if ( s!= null && s.Name.Contains("Room"))
            {
                s.Width = 400;
                s.Height = 400;
            }
        }

        /// <summary>
        /// Adds a CAD drawing to the Visio drawing control
        /// </summary>
        /// <param name="filename">The name of the dwg file</param>
        /// <param name="x">The x coordinate</param>
        /// <param name="y">The Y coordinate</param>
        private SellableShape AddDWG(string filename, double x, double y)
        {            
#warning il path dovrà essere gestito in maniera più intelligente
            // determines the CAD filepath
            string path = Environment.CurrentDirectory + "/DemoFiles/Cads/" + filename;
            // enables the dwg adding context
            AddingDWG = true;
            /* finds the Insert CAD addon and runs it with its two parameters.
             * unit of measure and file path must be provided.
             * This command will raise the ShapeAdded event on the drawing control
             */ 
            _drawingControl.Window.Application.Addons.ItemU["Insert AutoCAD Drawing"]
                .Run("/unit=CM " + path);

            // finds the details of the product
#warning questi dati andranno recuperati dal database - MagentoCoreAPI
            Models.ProductDetailsModel detail = StaticUtils.DWGs.getSize(filename);
            try
            {
                // creates the shape             
                var new_shape = new SellableShape(DWG, detail);
                // put the shape in the right location
                new_shape.Pin = new Point(x, y);
                // adds the shape to the viewModel and on the shape "manager"
                VM.Add(new_shape);
                // Adds the reference of the shape to the statemanager
                State[ActivePageIndex].AddShape(new_shape);
                // adds to the added shape the  handler to the CellChanged event
                new_shape.VisioShape.CellChanged += new Visio.EShape_CellChangedEventHandler(shape_CellChanged);
                return new_shape;
            }
            catch (Exception e) { return null; }
        }
        

        #region INITIALIZATION

        /// <summary>
        /// Common construction steps  of the page.
        /// </summary>
        private void CommonConstructionSteps()
        {
            InitializeComponent();
            this.Loaded += (s, e) =>
            {
                //_drawingControl.Window.Zoom = 0.7;
                _zoomSilder.Value = 1.2;
                _drawingControl.Window.ZoomLock = false;                
                //_drawingControl.Window.ZoomBehavior = Visio.VisZoomBehavior.visZoomInPlaceContainer;
                //_WFHost.Visibility = System.Windows.Visibility.Collapsed;		
#if DEBUG
                System.Diagnostics.Debug.WriteLine(this._productsLB.ActualHeight.ToString());
#endif
            };
        }

        /// <summary>
        /// Drawing control initialization based on the selected page setup
        /// </summary>
        /// <param name="setup">The setup parameters of the drawing control</param>
        private void InitializeDrawingControl(PageSetup setup)
        {
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PageWidth"]
                .set_Result(Visio.VisUnitCodes.visMillimeters, setup.PageWidth);

            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PageHeight"]
                .set_Result(Visio.VisUnitCodes.visMillimeters, setup.PageHeight);

            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PageScale"]
                .set_Result(Visio.VisUnitCodes.visMillimeters, setup.PageScale);

            _drawingControl.Window.PageAsObj.PageSheet.CellsU["DrawingScale"]
                .set_Result(Visio.VisUnitCodes.visMillimeters, setup.DrawingScale);

            _drawingControl.Window.PageAsObj.PageSheet.CellsU["DrawingScaleType"]
                .ResultIU = 2;
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["DrawingSizetype"]
                .ResultIU = 0;
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["DrawingResizetype"]
                .ResultIU = 2;

            // print setup
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PaperSource"]
                .ResultIU = 7;
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PrintPageOrientation"]
                .ResultIU = 2;
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PaperKind"]
                .ResultIU = 9;
            _drawingControl.Window.PageAsObj.PageSheet.CellsU["PrintGrid"]
                .ResultIU = 1;


            _drawingControl.Window.ShowRulers = 1;
            _drawingControl.Window.ShowGrid = 1;            
        }

        /// <summary>
        /// Loads the basic stencils of visio.
        /// </summary>
        private void LoadBasicStencil()
        {
#warning dovrebbe essere fatto da XML
            #region CARICAMENTO DWG FITTIZI - Presi da i dati di esempio
            foreach (var item in StaticUtils.DWGs.lista)
            {
                VM.Products.Add(new ProductModel()
                {
                    DisplayName = item.ProductName,
                    DWGFileName = item.CadFilePath,
                    ImagePath = item.ImagePath,
#warning ci dovrà essere il vero product id
                    ProductID = item.PSMNTProductCode
                }
                    );
            }

            #region DA ELIMINARE
            var itemmm = StaticUtils.DWGs.lista[0];
            for (int i = 0; i < 33; i++)
            {
                VM.Products.Add(new ProductModel()
                {
                    DisplayName = itemmm.ProductName,
                    DWGFileName = itemmm.CadFilePath,
                    ImagePath = itemmm.ImagePath,
                    ProductID = itemmm.PSMNTProductCode
                }
                    );
            }
            #endregion

            #endregion

            // Loads from XML the list of selected Visio Standard Stencils
            XElement elem = XElement.Load(Environment.CurrentDirectory + "/Resources/MastersCategory.xml");
            var a = elem.Elements().Select(x =>
                new
                {
                    NameU = x.Element("NameU").Value,
                    Cat = MastersCategoriesDictionary.FromCategoryName(
                        x.Element("Category").Value)
                });
            ;

            /* Iterates through all the predefined stencils and loads
             * only the stencils selected and annotated with the category
             * */
            foreach (var element in StencilPaths)
            {
                var stencil = VisioUtility
                .OpenStencil(_drawingControl, element);
                foreach (Visio.Master item in stencil.Masters)
                {
                    var assoc = a.FirstOrDefault(x => x.NameU == item.NameU);
                    if (assoc != null)
                    {
                        VM.Masters.Add(new MasterModel()
                        {
                            Master = item,
                            Image = VisioUtility.GetImageFromMasterPicture(item.Picture),
                            Category = assoc.Cat
                        });
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// Gets the index of the active page
        /// </summary>
        private int ActivePageIndex
        {
            get { return _drawingControl.Window.Application.ActivePage.ID; }
        }

        private Point SetDraggedProduct(Point point)
        {
            DependencyObject dobj = GetListBoxItemFromPosition(point);
            if (dobj != null)
            {
                Dragging = true;
                draggedMaster = (dobj as ListBoxItem).DataContext as MasterModel;
            }
            return point;
        }

        #region VisualTree Navigation Helpers
        private DependencyObject GetListBoxItemFromPosition(Point point)
        {            
            var result =
                VisualTreeHelper.HitTest(this, point);
            DependencyObject dobj = result.VisualHit;

            dobj = GetListboxItemParent(dobj);
            return dobj;
        }

        private static DependencyObject GetListboxItemParent(DependencyObject dobj)
        {
            while (dobj != null && !(dobj is ListBoxItem))
            {
                var b = VisualTreeHelper.GetParent(dobj);
                dobj = b;
            }
            return dobj;
        } 
        #endregion

        #region Da sistemare o sostituire        
        private void Scorri_TouchUp(object sender, TouchEventArgs e)
        {
            VM.CurrentPage++;
        }
        private void scorri_Click(object sender, RoutedEventArgs e)
        {
            VM.CurrentPage++;
        }

        private void scorriSX_TouchUp(object sender, TouchEventArgs e)
        {
            VM.CurrentPage--;
        }                
        private void scorriSX_Click(object sender, RoutedEventArgs e)
        {
            VM.CurrentPage--;
        }
        #endregion        

        #region EVENT HANDLERS VISIO DRAWING CONTROL

        /// <summary>
        /// Event handler for the ShapeAdded event, raised whenever a shape is added to the
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _drawingControl_ShapeAdded(object sender, VisOcx.EVisOcx_ShapeAddedEvent e)
        {

#warning l'ID è relativo alla pagina in cui l'oggetto viene aggiunto.
            if (!Duplicating)
            {
                if (AddingMeasure)
                {
                    // bisogna gestire correttamente il tipo
                    //shapes.Add(new MeasureShape(e.shape, MeasureType.Horizontal));
                    AddingMeasure = false;
                }
                else if (AddingDWG)
                {
                    DWG = e.shape;
                    AddingDWG = false;
                }
                else
                {
                    if (State[ActivePageIndex] != null)
                    {
                        var newShape = new ManagedShape(e.shape);
                        State[ActivePageIndex].AddShape(newShape);
                        //if the added shape is a room, it will became a 4m*4m room.
                        if (!CopyingDesign && e.shape.NameU.Contains("Room"))
                        {
                            newShape.Width=400;
                            newShape.Height=400;
                        }
                    }
                    e.shape.CellChanged += new Visio.EShape_CellChangedEventHandler(shape_CellChanged);
                }
            }
        }


        public void shape_CellChanged(Visio.Cell Cell)
        {            
            if (State[ActivePageIndex] != null)
            {
                var s = State[ActivePageIndex].Shapes.FirstOrDefault(x => x.ID == Cell.Shape.ID) as ManagedShape;
                s.SynchronizeProperty(Cell.Name, Cell.get_Result(StaticUtils.VisioCentimeters));
            }
        }        


        private void _drawingControl_MouseUpEvent(object sender, AxMicrosoft.Office.Interop.VisOcx.EVisOcx_MouseUpEvent e)
        {
            if ((e.button == (int)Visio.VisKeyButtonFlags.visMouseRight) &&
                ((e.keyButtonState & (int)Visio.VisKeyButtonFlags.visKeyControl) == 0))
            {
                e.cancelDefault = true;
                lastMousePosition = new Point(e.x, e.y);
                if (_drawingControl.ContextMenuStrip == null)
                {
                    SetupContextMenu();
                }
#warning ripristinare menù da click destro
                //_drawingControl.ContextMenuStrip.Show(_WFHost.Child, VisioUtility.MapVisioToWindows(_drawingControl, e.x, e.y));
            }
        }


        private void _drawingControl_SelectionChanged(object sender, VisOcx.EVisOcx_SelectionChangedEvent e)
        {
#if DEBUG
            if (e.window.Selection.Count > 1)
            {
                //MessageBox.Show(e.window.Selection.Count.ToString() + " selected shapes");
                bool cont = VisioUtility.IsContained(
                    new Point(e.window.Selection[1].CellsU["PinX"].get_Result(StaticUtils.VisioCentimeters),
                              e.window.Selection[1].CellsU["PinY"].get_Result(StaticUtils.VisioCentimeters)),
                    new Point(e.window.Selection[1].CellsU["Width"].get_Result(StaticUtils.VisioCentimeters),
                              e.window.Selection[1].CellsU["Height"].get_Result(StaticUtils.VisioCentimeters)),
                    new Point(e.window.Selection[2].CellsU["PinX"].get_Result(StaticUtils.VisioCentimeters),
                              e.window.Selection[2].CellsU["PinY"].get_Result(StaticUtils.VisioCentimeters)),
                    new Point(e.window.Selection[2].CellsU["Width"].get_Result(StaticUtils.VisioCentimeters),
                              e.window.Selection[2].CellsU["Height"].get_Result(StaticUtils.VisioCentimeters))
                    );
                //MessageBox.Show(cont ? "is contained" : "is not contained");
            }
#endif
        }

        private void Window_TouchUp(object sender, TouchEventArgs e)
        {
            var p = e.GetTouchPoint(_WFHost).Position;
            p = SetDraggedElement(p);
        }

        private void _WFHost_MouseUp(object sender, MouseButtonEventArgs e)
        {
            var p = e.GetPosition(_WFHost);
            p = SetDraggedElement(p);
        }

        private Point SetDraggedElement(Point p)
        {
            if (Dragging)
            {
                if (p.X >= 0 && p.Y >= 0 && p.X <= _WFHost.ActualWidth && p.Y <= _WFHost.ActualHeight)
                {
                    if (draggedMaster != null)
                    {
                        var shapeToAdd = draggedMaster;
                        AddShapeToVisioCanvas(shapeToAdd, p.X, p.Y);
                    }
                    if (draggedProduct != null)
                    {
                        Point pos = VisioUtility.MapWindowsToVisio(_drawingControl, p.X, p.Y);
                        AddDWG(draggedProduct.DWGFileName, VisioUtility.InchToCm(pos.X), VisioUtility.InchToCm(pos.Y));
                    }
                }
                Dragging = false;
                draggedMaster = null;
                draggedProduct = null;
            }
            return p;
        }

        /// <summary>
        /// Manages shapes cancelation in order to synchronize the VM and the STATE
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _drawingControl_BeforeSelectionDelete(object sender, VisOcx.EVisOcx_BeforeSelectionDeleteEvent e)
        {
            int[] IDs = new int[e.selection.Count];
            for (int i = 1; i < e.selection.Count + 1; i++)
            {
                IDs[i - 1] = e.selection[i].ID;
            }
            for (int i = 0; i < IDs.Length; i++)
            {
                var sh = State[ActivePageIndex].Shapes.FirstOrDefault(x => x.ID == IDs[i]);
                if (sh is SellableShape)
                {
                    VM.Remove(sh as SellableShape);
                    State[ActivePageIndex].RemoveShape(sh);
                }
            }
        }


        private void _drawingControl_PageAdded(object sender, VisOcx.EVisOcx_PageAddedEvent e)
        {
            State.PageAdded(e.page.ID, e.page.NameU);
        }

        private bool _drawingControl_QueryCancelPageDelete(object sender, VisOcx.EVisOcx_QueryCancelPageDeleteEvent e)
        {
            MessageBoxResult result =
                MessageBox.Show("Cancellare la pagina e tutto il suo contenuto?", "Cancella pagina",
                    MessageBoxButton.OKCancel);

            if (result == MessageBoxResult.OK)
            {
                State.PageRemoved(e.page.ID);
                return false;
            }
            else
            {
                return true;
            }
        }


        #endregion

        public static childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
        {
            // Search immediate children first (breadth-first)
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);

                if (child != null && child is childItem)
                    return (childItem)child;

                else
                {
                    childItem childOfChild = FindVisualChild<childItem>(child);

                    if (childOfChild != null)
                        return childOfChild;
                }
            }

            return null;
        }                       
        

        #region EVENT HANDLERS WINDOW

        private void ExcelBT_TouchUp(object sender, TouchEventArgs e)
        {
            ExcelBT_Click(null, null);
        }        

        /// <summary>
        /// Esportazione del preventivo su excel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExcelBT_Click(object sender, RoutedEventArgs e)
        {
            #region CommentedCode
            //            Excel.Application xcl = null;
            //            Excel.Workbook wbook;
            //            Excel.Worksheet wsheet;
            //            object missingValue = System.Reflection.Missing.Value;

            //            try
            //            {
            //                //Start Excel and get Application object.
            //                xcl = StartExcel();

            //                xcl.WindowActivate += (wb, wn) =>
            //                {
            //                    Dispatcher.BeginInvoke(new Action(() =>
            //                    App.Current.MainWindow.WindowState = WindowState.Minimized));
            //                };
            //                xcl.WindowDeactivate += (wb, wn) =>
            //                {
            //                    Dispatcher.BeginInvoke(new Action(() =>
            //                    App.Current.MainWindow.WindowState = WindowState.Maximized));
            //                };

            //                xcl = new Excel.Application();

            //                wbook = xcl.Workbooks.Add(missingValue);
            //                var pages = State.PagesAsEnumerable.ToArray();
            //                for (int pageIndex = 0; pageIndex < State.PagesCount; pageIndex++)
            //                {
            //                    wsheet = (Excel.Worksheet)wbook.Worksheets.get_Item(pageIndex + 1);
            //                    wsheet.Name = pages[pageIndex].PageName;
            //                    var bla = xcl.ActiveSheet.Pictures;
            //                    //.Insert(Environment.CurrentDirectory + "/Images/Drawing/background.png");

            //                    wsheet.Cells[2, 2] = "Passamonti SRL";
            //                    wsheet.Rows[2].Font.Bold = true;
            //                    wsheet.Rows[2].Font.Size = 14;

            //                    wsheet.Cells[2, 4] = "Preventivo Ufficio";
            //                    wsheet.Cells[2, 5] = "Francesco Mele";
            //                    wsheet.Rows[3].Font.Bold = true;
            //                    wsheet.Rows[3].Font.Size = 12;
            //                    wsheet.Cells[3, 2] = "Produttore";
            //                    wsheet.Cells[3, 3] = "Nome Prodotto";
            //                    wsheet.Cells[3, 4] = "Prezzo Unitario";
            //                    wsheet.Cells[3, 5] = "Quantità";
            //                    wsheet.Cells[3, 6] = "Costo Totale";

            //                    int lastRow = 5;
            //                    //for (int i = 0; i < VM.SelectedProducts.Count; i++)
            //                    for (int i = 0; i < pages[pageIndex].SelectedProducts.Count; i++)
            //                    {
            //                        #region inserimento immagine
            //                        InvoiceModel invoice = pages[pageIndex].SelectedProducts[i];                        
            //                        Excel.Range r = wsheet.get_Range("A" + (5 + i).ToString(), "A" + (5 + i).ToString());
            //                        System.Drawing.Image image = System.Drawing.Bitmap.FromFile(Environment.CurrentDirectory +
            //                        invoice.Product.ProductDetails.ImagePath);
            //                        //VM.SelectedProducts[i].Product.ProductDetails.ImagePath);

            //                        double maxDim = Math.Max(image.Width, image.Height);
            //                        double ratio = 99 / maxDim;
            //                        int new_width = (int)(image.Width * ratio);
            //                        int new_height = (int)(image.Height * ratio);

            //                        System.Drawing.Bitmap resizedImage = new System.Drawing.Bitmap(new_width, new_height);
            //                        System.Drawing.Graphics g = System.Drawing.Graphics.FromImage((System.Drawing.Image)resizedImage);
            //                        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            //                        g.DrawImage(image, 0, 0, new_width, new_height);

            //                        Clipboard.SetDataObject(resizedImage);
            //                        wsheet.Select();
            //                        r.Select();
            //                        wsheet.Paste(missingValue, missingValue);
            //                        System.Threading.Thread.Sleep(1000);
            //                        // corrispondente di 99 pixel per le righe e le colonne
            //                        r.EntireRow.RowHeight = 76;
            //                        r.EntireColumn.ColumnWidth = 13.5;
            //                        #endregion
            //                        wsheet.Cells[5 + i, 2] = invoice.Product.ProductDetails.Manufacturer;
            //                        wsheet.Cells[5 + i, 3] = invoice.Product.ProductDetails.ProductName;
            //                        wsheet.Cells[5 + i, 3] = invoice.Product.ProductDetails.ProductName;
            //                        wsheet.Cells[5 + i, 4].NumberFormat = "#.##0,00€";
            //                        wsheet.Cells[5 + i, 4] = invoice.Product.ProductDetails.PriceNoVAT;
            //                        wsheet.Cells[5 + i, 5] = invoice.Quantity;
            //                        wsheet.Cells[5 + i, 6].NumberFormat = "#.##0,00€";
            //                        //wsheet.Cells[5 + i, 6] = VM.SelectedProducts[i].TotalCost;
            //                        wsheet.Cells[5 + i, 6] = "=D" + (5 + i).ToString() + "* E" + (5 + i).ToString();
            //                        lastRow = 5 + i + 2;
            //                    }

            //                    wsheet.Cells[lastRow, 5] = "Totale";
            //                    wsheet.Cells[lastRow, 6].NumberFormat = "#.##0,00€";
            //#warning da sostituire con una formula
            //                    wsheet.Cells[lastRow, 6] = pages[pageIndex].TotalCost; //VM.TotalCost; 

            //                    wsheet.Cells[lastRow, 5].Font.Size = 12;
            //                    wsheet.Cells[lastRow, 6].Font.Size = 12;

            //                    wsheet.Cells[lastRow + 1, 5] = "Sconto";
            //                    wsheet.Cells[lastRow + 1, 6] = 0.12;
            //                    wsheet.Cells[lastRow + 1, 6].NumberFormat = "0,00%";
            //                    wsheet.Cells[lastRow + 1, 5].Font.Size = 12;
            //                    wsheet.Cells[lastRow + 1, 6].Font.Size = 12;

            //                    wsheet.Cells[lastRow + 2, 5] = "Totale a Pagare";
            //                    wsheet.Cells[lastRow + 2, 6].NumberFormat = "#.##0,00€";
            //                    wsheet.Cells[lastRow + 2, 6] = "=F" + lastRow.ToString() + "* (100% - F" + (lastRow + 1).ToString() + ")";
            //                    wsheet.Cells[lastRow + 2, 5].Font.Size = 12;
            //                    wsheet.Cells[lastRow + 2, 6].Font.Size = 14;
            //                    wsheet.Cells[lastRow + 2, 6].Font.Bold = true;

            //                    //Excel.Range xlrange = 
            //                    wsheet.Columns[2].Autofit();
            //                    wsheet.Columns[3].Autofit();
            //                    wsheet.Columns[4].Autofit();
            //                    wsheet.Columns[5].Autofit();
            //                    wsheet.Columns[6].Autofit();

            //                }
            //                xcl.Visible = true;
            //                xcl.UserControl = true;
            //                wbook.PrintPreview();
            //            }
            //            catch (Exception)
            //            {

            //                throw;
            //            }

            #endregion

            Helpers.ExcelHelper excelHelper = new ExcelHelper();            
            excelHelper.CreateExcelWorkbook(State);
            excelHelper.Show();
            //excelHelper.Print();
        }

        private void _zoomSilder_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (e.OldValue != 0)
            {
                _drawingControl.Window.Zoom = e.NewValue;
            }
        }

        private void _MasterLB_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            var point = e.GetTouchPoint(this).Position;
            point = SetDraggedProduct(point);
        }        


        private void _MasterLB_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var point = e.GetPosition(this);
            point = SetDraggedProduct(point);
        }

        private void _productsLB_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            var p = e.GetTouchPoint(this).Position;
            DependencyObject dobj = GetListBoxItemFromPosition(p);

            if (dobj != null)
            {
                Dragging = true;
                draggedProduct = (dobj as ListBoxItem).DataContext as ProductModel;
            }
        }
        private void _productsLB_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var p = e.GetPosition(this);
            DependencyObject dobj = GetListBoxItemFromPosition(p);

            if (dobj != null)
            {
                Dragging = true;
                draggedProduct = (dobj as ListBoxItem).DataContext as ProductModel;
            }
        }

        private void DeleteProductTB_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("This should delete the product");
            ListBoxItem item = GetListboxItemParent(sender as TextBlock) as ListBoxItem;
            if (item != null)
            {
                VM.RemoveProduct(item.DataContext as ProductModel);
            }
        }

        private void ZoomProductTB_TouchUp(object sender, TouchEventArgs e)
        {
            ZoomProductTB_MouseLeftButtonDown(sender, null);
        }        
        private void ZoomProductTB_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ListBoxItem item = GetListboxItemParent(sender as TextBlock) as ListBoxItem;
            if (item != null)
            {
                ProductModel product = item.DataContext as ProductModel;
                if (product != null)
                {
                    //_zoomSilder.Visibility = System.Windows.Visibility.Hidden;
                    var d = new Data.DWGSizes().getSize(product.ProductID);
                    
                    if (_frame.Visibility == System.Windows.Visibility.Visible)
                    {
                        (_frame.Content as Pages.ProductDetailsPage).ChangeProduct(d);
                    }
                    else
                    {
                        
                        Point relativePoint = _WFHost.TransformToAncestor(this).Transform(new Point(0, 0));                        
                        var screenBounds = System.Windows.Forms.Screen.AllScreens[0].Bounds;                        
                        var resizedImage = new System.Drawing.Bitmap(_drawingControl.Width, _drawingControl.Height);                        
                        var src = System.Drawing.Graphics.FromImage(resizedImage);
                        src.CopyFromScreen((int)relativePoint.X, (int)relativePoint.Y, 0, 0,
                            new System.Drawing.Size(resizedImage.Width, resizedImage.Height));
                        resizedImage.Save(Environment.CurrentDirectory + "//Images//CurrentBackground.png", ImageFormat.Png);

                        // hides drawing control and shows details page.
                        _WFHost.Visibility = System.Windows.Visibility.Collapsed;
                        _frame.Visibility = System.Windows.Visibility.Visible;
                        _frame.Navigate(new Pages.ProductDetailsPage(d));
                    }
                }
            }
        }

        private void _productsLB_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dobj = GetListBoxItemFromPosition(e.GetPosition(this));
            ProductModel product;
            if (dobj != null)
            {
                product = (dobj as ListBoxItem).DataContext as ProductModel;

                if (product != null)
                {
                    //_zoomSilder.Visibility = System.Windows.Visibility.Hidden;
                    var d = new Data.DWGSizes().getSize(product.ProductID);
                    _WFHost.Visibility = System.Windows.Visibility.Collapsed;
                    if (_frame.Visibility == System.Windows.Visibility.Visible)
                    {
                        (_frame.Content as Pages.ProductDetailsPage).ChangeProduct(d);
                    }
                    else
                    {
                        _frame.Visibility = System.Windows.Visibility.Visible;
                        _frame.Navigate(new Pages.ProductDetailsPage(d));
                    }
                }
            }
        }

        private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var bla = (sender as ListBox);
            VM.ChangeCategory((Models.MasterCategory)bla.SelectedItem);
        }

        private void _drawingControl_PageChanged(object sender, VisOcx.EVisOcx_PageChangedEvent e)
        {
            if (State[e.page.ID] != null)
            {
                State[e.page.ID].PageName = e.page.NameU;
            }
        }

        private void PrintBT_TouchUp(object sender, TouchEventArgs e)
        {
            MessageBox.Show(_drawingControl.Window.Document.Printer);
            _drawingControl.Window.Document.Print();
        }        

        private void Print_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(_drawingControl.Window.Document.Printer);
            _drawingControl.Window.Document.Print();

            //_drawingControl.Window.Document.PrintOut(Visio.VisPrintOutRange.visPrintAll, 1, -1, false, "", true,
            //    "Preventivo.pdf", 1, false, false);
        }

        private void ScrollDownButton_TouchUp(object sender, TouchEventArgs e)
        {
            ScrollDownButton_Click(null, null);
        }
        private void ScrollDownButton_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = FindVisualChild<ScrollViewer>(_MasterLB);
            if (sv.VerticalOffset < sv.ExtentHeight)
            {
                double offset = (double)_MasterLB.ItemContainerGenerator.ContainerFromIndex(0).GetValue(ListBoxItem.ActualHeightProperty);
                sv.ScrollToVerticalOffset(sv.VerticalOffset + offset);
            }
        }

        private void ScrollUpButton_TouchUp(object sender, TouchEventArgs e)
        {
            ScrollUpButton_Click(null, null);
        }        
        private void ScrollUpButton_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = FindVisualChild<ScrollViewer>(_MasterLB);
            if (sv.VerticalOffset > 0)
            {
                double offset = (double)_MasterLB.ItemContainerGenerator.ContainerFromIndex(0).GetValue(ListBoxItem.ActualHeightProperty);
                sv.ScrollToVerticalOffset(sv.VerticalOffset - offset);
            }
        }

        private void _MasterLB_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            ScrollViewer sv = FindVisualChild<ScrollViewer>(_MasterLB);

            if (sv.VerticalOffset >= sv.ScrollableHeight - 20)
                ScrollDownButton.IsEnabled = false;
            else ScrollDownButton.IsEnabled = true;

            if (sv.VerticalOffset <= 20)
                ScrollUpButton.IsEnabled = false;
            else ScrollUpButton.IsEnabled = true;
        }
                
        private void DuplicateBT_TouchUp(object sender, TouchEventArgs e)
        {
            DuplicateBT_Click(null, null);
        }        

        private void DuplicateBT_Click(object sender, RoutedEventArgs e)
        {
//            MessageBox.Show(
//                @"Dovrà ciclare nella selezione e aggiungere nuovamente tutte le forme selezionate
//                aggiungento sia al drawing control, sia allo stato, in maniera corretta
//                (richiamando i metodi corretti)");
            var selection = _drawingControl.Window.Selection;
            Visio.Selection PostDuplicationSelection = 
                _drawingControl.Window.Application.ActivePage.CreateSelection(Visio.VisSelectionTypes.visSelTypeEmpty);            
            Duplicating = true;
            for (int i = 1; i <= selection.Count; i++)
            {
                
                var s = State[this.ActivePageIndex].Shapes.FirstOrDefault(x => x.ID == selection[i].ID);
                if (s != null)
                {
                    var DuplicatedShape = selection[i].Duplicate();
                    PostDuplicationSelection.Select(DuplicatedShape, (short)Visio.VisSelectArgs.visSelect);
                    //simple shape
                    if (s is SellableShape)
                    {
                        if (State[ActivePageIndex] != null)
                        {
                            State[ActivePageIndex].AddShape
                                (new SellableShape(DuplicatedShape, (s as SellableShape).ProductDetails));
                        }
                    }
                    else
                    {
                        if (State[ActivePageIndex] != null)
                        {
                            State[ActivePageIndex].AddShape(new ManagedShape(DuplicatedShape));
                        }
                        DuplicatedShape.CellChanged += new Visio.EShape_CellChangedEventHandler(shape_CellChanged);
                    }                    
                }
            }
            Duplicating=false;
            //_drawingControl.Window.Selection = selection;
            _drawingControl.Window.Selection = PostDuplicationSelection;
        }

        private void DeleteProductTB_TouchUp(object sender, TouchEventArgs e)
        {
            _drawingControl.Window.Selection.Delete();
            // scatena l'evento BeforeSelectionDelete
        }

        private void DeleteBT_TouchUp(object sender, TouchEventArgs e)
        {
            _drawingControl.Window.Selection.Delete();
        }        
        private void DeleteBT_Click(object sender, RoutedEventArgs e)
        {
            _drawingControl.Window.Selection.Delete();
            // scatena l'evento BeforeSelectionDelete
        }

        private void RotateBT_TouchUp(object sender, TouchEventArgs e)
        {
            RotateBT_Click(null, null);
        }        
        private void RotateBT_Click(object sender, RoutedEventArgs e)
        {
            _drawingControl.Window.Selection.Rotate(
                90, Visio.VisUnitCodes.visDegrees,
                true, Visio.VisRotationTypes.visRotateSelection,
                0, 0, Type.Missing
                );
        }

        private void Zoom_TouchUp(object sender, TouchEventArgs e)
        {
            Zoom_Click(sender, null);
        }        

        private void Zoom_Click(object sender, RoutedEventArgs e)
        {
            if (sender.Equals(ZoomInBT))
            {
                _zoomSilder.Value += .25;
            }
            if (sender.Equals(ZoomOutBT))
            {
                _zoomSilder.Value -= .25;
            }
            if (sender.Equals(ZoomFitBT))
            {
                double L, R, B, T;
                var old_selection = _drawingControl.Window.Selection;
                _drawingControl.Window.Selection =
                    _drawingControl.Window.Application.ActivePage.CreateSelection(Visio.VisSelectionTypes.visSelTypeAll);
                if (_drawingControl.Window.Selection.Count != 0)
                {
                    _drawingControl.Window.Selection.BoundingBox((short)Visio.VisBoundingBoxArgs.visBBoxUprightWH,
                        out L, out B, out R, out T);
                    double w = R - L;
                    double H = T - B;
                    _drawingControl.Window.SetViewRect(L, T, R - L, T - B);
                    _zoomSilder.Value = _drawingControl.Window.Zoom;
                    _drawingControl.Window.Selection = old_selection;                        
                }
            }
        }

        private void Flip_TouchUp(object sender, TouchEventArgs e)
        {
            Flip_Click(sender, null);
        }        
        private void Flip_Click(object sender, RoutedEventArgs e)
        {
            if (sender == FlipHorBT)
            {
                _drawingControl.Window.Selection.FlipHorizontal();
            }
            if (sender == FlipVertBT)
            {
                _drawingControl.Window.Selection.FlipVertical();
            }
        }

        private void Align_TouchUp(object sender, TouchEventArgs e)
        {
            Align_Click(sender, null);
        }        
        private void Align_Click(object sender, RoutedEventArgs e)
        {
            if (sender == AlignHor)
            {
                _drawingControl.Window.Selection.Align(
                    Visio.VisHorizontalAlignTypes.visHorzAlignCenter,
                    Visio.VisVerticalAlignTypes.visVertAlignNone);
            }
            if (sender==AlignVert)
                _drawingControl.Window.Selection.Align(
                    Visio.VisHorizontalAlignTypes.visHorzAlignNone,
                    Visio.VisVerticalAlignTypes.visVertAlignMiddle);
    
        }
        #endregion        

        private void NewPageBT_TouchUp(object sender, TouchEventArgs e)
        {
            NewPageBT_Click(null, null);
        }        
        private void NewPageBT_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result =
                MessageBox.Show("Vuoi aggiungere una nuova pagina?", "Nuova Pagina", MessageBoxButton.YesNo);
            if (result  == MessageBoxResult.Yes)
            {                
                MessageBoxResult r2 =
                    MessageBox.Show("Vuoi creare una nuova proposta per questa stanza?", "Nuova proposta", MessageBoxButton.YesNo);
                
                int baseID = this.ActivePageIndex;
                var new_page = _drawingControl.Window.Document.Pages.Add();
                
                if (r2 == MessageBoxResult.Yes)
                {
                    CopyingDesign = true;
                    try
                    {
                        Visio.Selection copySelection =
                    _drawingControl.Window.Application.ActivePage.CreateSelection(Visio.VisSelectionTypes.visSelTypeEmpty);

                        foreach (var item in State[baseID].Shapes.Where(x => !(x is SellableShape)))
                        {
                            copySelection.Select(item.VisioShape, (short)Visio.VisSelectArgs.visSelect);
                        }

                        if (copySelection.Count > 0)
                        {
                            copySelection.Copy(Visio.VisCutCopyPasteCodes.visCopyPasteNoTranslate);
                            new_page.Paste(Visio.VisCutCopyPasteCodes.visCopyPasteNoTranslate);
                        }
                    }
                    catch(Exception){}
                }                
            }
        }

        private void HelpBT_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Questo pulsante dovrà aprire l'help online.");

        }        
    }
}